#include <FreeRTOS_AVR.h>
#include <LiquidCrystal.h>

#define s_delay(A) vTaskDelay((AL * configTICK_RATE_HZ) / 1000L)
/*
  struct
  {
    const short D4;
    const short D5;
    const short D6;
    const short D7;
  } lcd_pins;
*/
  struct
  {
    const short echo=3;
    const short trig=4;
  } distance_sensor_pins;

const int env_brightness_sensor = A5;
const int light = 3;
const short beep = 5;

struct {
  const short switch1 = 0; // run/stop
  const short switch2 = 1; // clear
} switches;

SemaphoreHandle_t sem_tobeep;
SemaphoreHandle_t sem_totimer;
SemaphoreHandle_t sem_totimerclear;

int timer_status = 1; // 1run,2stop
int timer_clear = 0;

void LCD_show(unsigned long i) {}

static void check_switch(void *arg) {
  pinMode(switches.switch1, INPUT_PULLUP);
  pinMode(switches.switch2, INPUT_PULLUP);
  while (1) {
    if (digitalRead(switches.switch1) == LOW) {
      xSemaphoreGive(sem_totimer);
      vTaskDelay((200L * configTICK_RATE_HZ) / 1000L);
    }
    if (digitalRead(switches.switch2) == LOW) {
      xSemaphoreGive(sem_totimerclear);
      vTaskDelay((200L * configTICK_RATE_HZ) / 1000L);
    }
  }
}

static void beep_fuck(void *arg) {
  pinMode(beep, OUTPUT);
  while (1) {
    xSemaphoreTake(sem_tobeep, portMAX_DELAY);
    tone(beep,10);
    vTaskDelay((5000L * configTICK_RATE_HZ) / 1000L);
    noTone(beep);
  }
}

static void check_time(void *arg) {
  unsigned long start = millis();
  unsigned long now;
  while (1) {
    if (timer_status == 1) {
      now = millis();
      if ((now - start) / 1000 >= 3600) {
        xSemaphoreGive(sem_tobeep);
        LCD_show(now - start);
        start = millis();
      }
    }
    if (timer_status == 2) {
      start = millis();
    }
    if (timer_clear) {
      start = millis();
      now = 0;
      timer_clear = 0;
    }
  }
}

static void timer(void *arg) {
  while (1) {
    xSemaphoreTake(sem_totimer, portMAX_DELAY);
    timer_status = timer_status % 3;
    while (digitalRead(switches.switch1) == LOW)
      ;
  }
}

static void timer_clear_fuck(void *arg) {
  while (1) {
    xSemaphoreTake(sem_totimerclear, portMAX_DELAY);
    timer_status = 2;
    timer_clear = 1;
  }
  while (digitalRead(switches.switch1) == LOW)
    ;
}

static void ctrl_light(void *arg) {
 pinMode(light,OUTPUT);
  while (1) {
    analogRead(env_brightness_sensor);
  }
}

static void distance_alarm(void *arg) {
  pinMode(distance_sensor_pins.echo,INPUT);
  pinMode(distance_sensor_pins.trig,OUTPUT);
  while (1) {
    digitalWrite(distance_sensor_pins.trig,LOW);
    int start=millis();
    while((millis()-start)>=2);
    digitalWrite(distance_sensor_pins.trig,HIGH);
    start=millis();
    while((millis()-start)>=10);
    if(float(pulseIn(distance_sensor_pins.echo,HIGH))*17/1000<25.00)
    xSemaphoreGive(sem_totimer);
  }
}

void error_fuck() {
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  while (1)
    ;
}

void setup() {
  portBASE_TYPE s[7];
  sem_tobeep = xSemaphoreCreateCounting(1, 0);
  sem_totimer = xSemaphoreCreateCounting(1, 0);
  sem_totimerclear = xSemaphoreCreateCounting(1, 0);
  s[0] =
      xTaskCreate(check_switch, NULL, configMINIMAL_STACK_SIZE, NULL, 1, NULL);
  s[1] = xTaskCreate(beep_fuck, NULL, configMINIMAL_STACK_SIZE, NULL, 2, NULL);
  s[2] = xTaskCreate(check_time, NULL, configMINIMAL_STACK_SIZE, NULL, 3, NULL);
  s[3] = xTaskCreate(timer, NULL, configMINIMAL_STACK_SIZE, NULL, 4, NULL);
  s[4] = xTaskCreate(timer_clear_fuck, NULL, configMINIMAL_STACK_SIZE, NULL, 5,
                     NULL);
  s[5] = xTaskCreate(ctrl_light, NULL, configMINIMAL_STACK_SIZE, NULL, 6, NULL);
  s[7] = xTaskCreate(distance_alarm, NULL, configMINIMAL_STACK_SIZE, NULL, 7,
                     NULL);
  for (int i = 0; i < 7; i++)
    if (s[i] != pdPASS)
      error_fuck();
  if (sem_tobeep == NULL | sem_totimer == NULL | sem_totimerclear == NULL)
    error_fuck();
  vTaskStartScheduler();
  while (1)
    ; // Don't edit!
}

void loop() {
  // Do nothing
}
